#ifndef INTERRUPTVERWALTUNG_H_
#define INTERRUPTVERWALTUNG_H_

#include "constants.h"
#include <sys/neutrino.h>
#include <stdlib.h>
#include "HWaccess.h"
#include <pthread.h>
#include <semaphore.h>
#include <malloc.h>
#include <errno.h>
#include <sys/mman.h>
#include <process.h>

#ifdef SIMULATION
#include <ioaccess.h>
#endif

#define LISTSIZE 12
#define ISR_MESSAGE_CODE 10

/**
 * \struct listItem
 *
 * \brief struct to handle the interrupts and their message contents
 * \param next pointer to the next item
 * \param channelID channel on which the messages will be sent
 * \param connectionID the connection id
 * \param pin the process identification number
 * \param messageCode the code which the message will send
 * \param messageContent the content of the message
 * \param pid the process id
 */
struct listItem{
    struct listItem* next;
    int channelID;
    int connectionID;
    int pin;
    char messageCode;
    int messageContent;
    pid_t pid;
};

/**
 * \brief class to handle interrupts
 *
 * This class provides easy, thread save access for change of state interrupts for the DIO-Board 104-DIO.
 * If a listener is added for one pin, it will recieve the previously defined pulse-message, when the state of the given pin changed.
 */
class Interruptverwaltung{

private:
    struct listItem * list[LISTSIZE]; // contains Listheads. list[0] to list[7] PORTB; list[8] to list[11] PORTC
    int lastValB;
    int lastValC;
    volatile int irqStatus;
    volatile bool running;
    pthread_t pthread;
    pthread_mutex_t lockLists;
    sem_t waitForInit;

    static pthread_mutex_t lockSingleton;
    static Interruptverwaltung * instance;

    int init();
    Interruptverwaltung();
    virtual ~Interruptverwaltung();
    static const struct sigevent * InterruptverwaltungISR(void *arg, int id);
    static void * InterruptverwaltungManagementThreadRoutine(void * arg);
    static void InterruptverwaltungSendPulses(struct listItem * first);

public:
    /**
     * \brief Adds listener for given pin.
     *
     * \param channelID contains the channel, which should receive the pulse-messages.
     * \param pid contains the pid of the receiving thread.
     * \param messageCode contains the code of the pulse-message.
     * \param messageContent contains the content of the pulse-message.
     * \returns 0 if successful, -1 on failure.
     */
    int addListener(int channelID, pid_t pid, int pin, char messageCode, int messageContent);

    /**
     * \brief Removes a listener.
     *
     * \param channelID contains the channel, defined when adding the listener.
     * \param pid contains the pid, defined when adding the listener.
     * \param pin contains the pin, defined when adding the listener.
     */
    int removeListener(int channelID, pid_t pid, int pin);

    /**
     * \brief Getter for the singleton-instance of Interruptverwaltung.
     *
     * \returns Instance of interrupt control
     */
    static Interruptverwaltung * getInstance();



};

#endif /* INTERRUPTVERWALTUNG_H_ */
